package stage
{
	import edu.pku.component.MsgBox;
	import edu.pku.controller.util.RegionPoint;
	
	import flash.display.Graphics;
	import flash.events.Event;
	import flash.utils.clearInterval;
	
	import mx.collections.ArrayCollection;

	public class DynamicTrack extends OrderSprite
	{
		public var arrayPoints:ArrayCollection=new ArrayCollection();
		
		public var pointBuffer:Array=new Array();
		
		public var drawInterval:uint;
		
		/**
		 * draw color of the line and the cycle
		 * @default 
		 */
		public var drawColor:uint=AppConstant.COLOR_RED;
		
		public function setDrawColor(color:uint):void
		{
			this.drawColor=color;
		}
		
		private var draw_parts:Number=10.0;
		
		private var draw_inteval:Number=1000.0/draw_parts;
		
		public function DynamicTrack()
		{
			super(AppConstant.ORDER_SECOND);
			//setInterval(drawOnePoint,draw_inteval);
//			this.addEventListener(Event.ENTER_FRAME,myEnterFrame);
//			var points:Array = [{x:10,y:20,radius:10},{x:300,y:40,radius:10},{x:60,y:60,radius:10},{x:80,y:100,radius:10},{x:70,y:150,radius:10},{x:20,y:100,radius:10}];
//			arrayPoints.addAll(points);
						
		}
		
		private var pointAdded:Boolean=false;
		
		public function myEnterFrame(event:Event):void
		{
			if(pointAdded)
			{
				//trace("enter frame");
				drawLine(arrayPoints);
				pointAdded=false;
			}
		}
		
		private function drawOnePoint():void
		{
			if(pointBuffer.length>0)
			{
				if(lastDrawPoint==null)
				{
					lastDrawPoint=pointBuffer.shift();
					drawCircle(lastDrawPoint);				
				}
				else
				{
					var rp:Object=pointBuffer.shift();
					//drawNimbusLine(lastDrawPoint,rp,lastDrawPoint.radius);
					drawWideLine(lastDrawPoint,rp,lastDrawPoint.radius);
					lastDrawPoint=rp;
				}
			}
		}
		
		private function breakLineToPart(p2:RegionPoint):void
		{
			if(arrayPoints.length>0)
			{
				var p1:RegionPoint=arrayPoints.getItemAt(arrayPoints.length-1) as RegionPoint;
				var parts:Number=draw_parts;
				var xstep:Number=(p2.x-p1.x)/parts;
				var ystep:Number=(p2.y-p1.y)/parts;
				for(var i:int=1;i<parts;i++)
				{
				
					var rp:Object={x:p1.x+i*xstep,y:p1.y+i*ystep,radius:p1.radius};
//					rp.x=p1.x+i*xstep;
//					rp.y=p1.y+i*ystep;
//					rp.radius=p1.radius;
					pointBuffer.push(rp);
				}
				pointBuffer.push(p2);
			}
			else // the first point
			{
				pointBuffer.push(p2);
			}
		}
		
		private var lastDrawPoint:Object=null;
		

		/**
		 * add a point to the current track
		 * @param regionPoint
		 */
		public function addPoint(regionPoint:RegionPoint):void{
			//clear the interval
			//clearInterval(this.drawInterval);
			//directly draw all the point
			//drawAllBufferPoint();
			//break line to part and insert point to pointBuffer
//			breakLineToPart(regionPoint);
			//add interval
			//drawInterval=setInterval(drawOnePoint,draw_inteval);			
			//add point to the array
//			arrayPoints.addItem(regionPoint);
//			drawOnePoint();

//			old draw point
			if(arrayPoints.length>0)
			{
				drawNimbusLine(arrayPoints[arrayPoints.length-1],regionPoint,regionPoint.radius);
			}
			arrayPoints.addItem(regionPoint);
//			drawCircle(regionPoint);
		}
		
		private var msgShowed:Boolean=false;
		
		public function messageShowed():Boolean
		{
			if(msgShowed)
			{
				return true;
			}
			else
			{
				if(this.arrayPoints.length==0)
				{
					msgShowed=true;
					return true;
				}
				else
					return false;
			}
		}
		
		public function getPointCount():int
		{
			if(this.arrayPoints==null)
				return 0;
			else
				return arrayPoints.length;
		}
		
		private function drawCircle(regionPoint:Object):void
		{
			var g:Graphics=this.graphics;
			g.lineStyle(1,drawColor,1);
			g.beginFill(drawColor,1);
			g.drawCircle(regionPoint.x, regionPoint.y, regionPoint.radius);
			g.endFill();
		}

		private function calculateStep(tP:Object,fP:Object):Object
		{
			var lineAngle:Number;
			lineAngle=Math.atan2(tP.y - fP.y, tP.x - fP.x);
			var ySolidLength:Number=-tP.radius * Math.cos(lineAngle);
			var xSolidLength:Number=tP.radius * Math.sin(lineAngle);
			return {x:xSolidLength,y:ySolidLength};
		}
		
		private function drawLine(drawPoints:ArrayCollection):void
		{
			graphics.clear();
			for (var i:int=0; i < drawPoints.length; i++)
			{
				var g:Graphics=this.graphics;
				g.lineStyle(1);
				g.beginFill(drawColor,1);
				g.drawCircle(drawPoints[i].x, drawPoints[i].y, drawPoints[i].radius);
				g.endFill();
			}
			graphics.lineStyle(1);
			for (i=0; i < drawPoints.length - 1; i++)
			{
				//drawDashLine(drawPoints[i], drawPoints[i + 1]);
				//drawTwoDashLine(drawPoints[i], drawPoints[i + 1]);
				drawWideLine(drawPoints[i],drawPoints[i+1],drawPoints[i].radius);
			}
		}
		
		/**
		 * 
		 * @param Fr circle point and radius
		 * @param To circle point and radius
 		 */
		private function drawTwoDashLine(p1:Object,p2:Object):void
		{
			var step:Object=calculateStep(p2,p1);
			drawDashLine({x:p1.x+step.x,y:p1.y+step.y},{x:p2.x+step.x,y:p2.y+step.y});
			drawDashLine({x:p1.x-step.x,y:p1.y-step.y},{x:p2.x-step.x,y:p2.y-step.y});
		}
		private function drawNimbusLine(p1:Object,p2:Object,radius:Number):void
		{
			var styleArray:Array=getStyleArray(radius);
			for(var i:int=0;i<styleArray.length;i++)
			{
				graphics.lineStyle(styleArray[i].radius,drawColor,styleArray[i].alpha);
				graphics.moveTo(p1.x,p1.y);
				graphics.lineTo(p2.x,p2.y);
			}
		}
		/**
		 * 
		 * @param radius
		 * @return 
		 */
		private function getStyleArray(radius:Number):Array
		{
			var styleArray:Array=new Array();
			if(radius==2)
			{
				styleArray.push({radius:4,alpha:0.5});
				styleArray.push({radius:2,alpha:0.5});
			}
			else if(radius==4)
			{
				styleArray.push({radius:8,alpha:0.3});
				styleArray.push({radius:4,alpha:0.4});
				styleArray.push({radius:2,alpha:0.3});
			}
			else if(radius==10)
			{
				styleArray.push({radius:20,alpha:0.25});
				styleArray.push({radius:15,alpha:0.25});
				styleArray.push({radius:10,alpha:0.25});
				styleArray.push({radius:5,alpha:0.25});
			}
			else
			{
				styleArray.push({radius:8,alpha:0.3});
				styleArray.push({radius:4,alpha:0.4});
				styleArray.push({radius:2,alpha:0.3});
			}
			return styleArray;
		}
		public function drawWideLine(p1:Object,p2:Object,radius:Number):void
		{
				graphics.lineStyle(radius*2,drawColor,0.2);
				graphics.moveTo(p1.x,p1.y);
				graphics.lineTo(p2.x,p2.y);
		}
		

		private function drawCurve(drawPoints:Array):void
		{
			graphics.clear();
			graphics.lineStyle(1);
			graphics.moveTo(drawPoints[0].x, drawPoints[0].y);
			for (var i:int=1; i < drawPoints.length - 1; i+=2)
			{
				graphics.curveTo(drawPoints[i].x, drawPoints[i].y, drawPoints[i + 1].x, drawPoints[i + 1].y);
			}
		}
		
		public function clearTrack():void
		{
			this.arrayPoints.removeAll();
			this.graphics.clear();
			this.lastDrawPoint=null;
			//remove all the point
		}
		
		public function drawDashLine(fP1:Object, tP1:Object):void
		{
			var g:Graphics=this.graphics;
			g.lineStyle(1);
			if (!fP1)
			{
				fP1={x: 0, y: 0,radius:5}
			}
			if (!tP1)
			{
				tP1={x: 0, y: 0,radius:5}
			}
			var fP:Object=null;
			var tP:Object=null;
			
			if(fP1.x>tP1.x)
			{
				fP=tP1;
				tP=fP1;
			}
			else
			{
				fP=fP1;
				tP=tP1;
			}			
			
			//applyLineStyle(vedge);

			var solidLength:Number=5;
			var brokenLength:Number=2;

			var lineAngle:Number;
			lineAngle=Math.atan2(tP.y - fP.y, tP.x - fP.x);

			var xSolidLength:Number=solidLength * Math.cos(lineAngle);
			var ySolidLength:Number=solidLength * Math.sin(lineAngle);

			var xBrokenLength:Number=brokenLength * Math.cos(lineAngle);
			var yBrokenLength:Number=brokenLength * Math.sin(lineAngle);

			var forwardFlag:Boolean=true;
			if (tP.y < fP.y)
			{
				forwardFlag=false;
			}
			var tempP:Object={x: fP.x, y: fP.y};
			var tempToP:Object={x: tP.x, y: tP.y};
			var lineType:String="solid";
			while (checkIn(tempP, tP, forwardFlag))
			{
				g.beginFill(drawColor);
				if (lineType == "solid")
				{
					tempToP.x=tempP.x + xSolidLength;
					tempToP.y=tempP.y + ySolidLength;
					g.moveTo(tempP.x, tempP.y);
					if(checkIn(tempToP,tP,forwardFlag))
					{
						g.lineTo(tempToP.x, tempToP.y);
					}
					else
					{
						g.lineTo(tP.x,tP.y);
					}
					lineType="space";
				}
				else
				{
					tempToP.x=tempP.x + xBrokenLength;
					tempToP.y=tempP.y + yBrokenLength;
					g.moveTo(tempToP.x, tempToP.y);
					lineType="solid";
				}
				tempP.x=tempToP.x;
				tempP.y=tempToP.y;
				g.endFill();
			}
		}

		private function checkIn(p:Object, toP:Object, forwardFlag:Boolean):Boolean
		{
			return forwardFlag ? p.x+p.y <= toP.x+toP.y : p.x-p.y <= toP.x-toP.y;
		}

	}
}